import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;

public class Test {
	//I didn't want to bother with worrying about whether assertions were enabled or not
	//so I just reimplemented them in terms of normal exceptions
	public static void verify(boolean condition, Object message) throws Exception {
		if (!condition) {
			throw new Exception(message.toString());
		}
	}
	public static void verify(boolean condition) throws Exception {
		Test.verify(condition, "Assertion Error");
	}
	public static void test(PrintStream out) {
		List<String> typeList;
		File outFile = new File("./out.txt");
		try {
			PrintStream output = new PrintStream(new FileOutputStream(outFile));
			PrintStream oldOut = System.out;
			System.setOut(output);
			Scanner input = Functions.readFile("testSpec01.txt");
			StringBuilder builder = new StringBuilder();
			while (input.hasNextLine()) {
				builder.append(input.nextLine());
				if (input.hasNextLine()) {
					builder.append("\n");
				}
			}
			System.out.println(builder.toString());
			DFA regexes = ScannerGenerator.dfaFromLexicalSpec("testSpec01.txt");
			DFA dfa = ScannerGenerator.dfaFromLexicalSpec("spec.txt");
			NFA nfa = ScannerGenerator.nfaFromLexicalSpec("spec.txt");
			dfa.tokenize(new Scanner(new File("file.txt")));
			System.setOut(oldOut);
			output.close();
			Scanner results = new Scanner(new BufferedReader(new FileReader(outFile)));
			typeList = new ArrayList<String>();
			while(results.hasNext()) {
				String line = results.next();
				if (line.startsWith("$")) {
					typeList.add(line);
				}
			}
			Map<String, Integer> counts = new HashMap<String, Integer>();
			for (String label: typeList) {
				if (counts.containsKey(label)) {
					counts.put(label, counts.get(label) + 1);
				}
				else {
					counts.put(label, 1);
				}
			}
			verify(typeList.get(0).equals("$IDENTIFIER"));
			verify(typeList.get(typeList.size() - 1).equals("$WEIRD"));
			verify(counts.get("$IDENTIFIER") == 5);
			verify(counts.get("$INT") == 3);
			verify(counts.get("$ASSIGN") == 3);
			verify(counts.get("$PRINT") == 1);
			verify(counts.get("$FLOAT") == 1);
			verify(counts.get("$MULTIPLY") == 1);
			verify(counts.get("$PLUS") == 1);
			out.println("Tests successfully run without error.");
			results.close();
			verify(true == outFile.delete());
		}
		catch (Exception error) {
			error.printStackTrace();
			outFile.delete();
			out.println(error);
			out.println("Tests failed.");
		}
	}
	public static void test() {
		Test.test(System.out);
	}
	
	public static void main(String[] args) {
		Test.test();
	}
}